package com.hibson.util;

import java.util.ArrayList;
import java.util.List;

import org.bson.Document;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * Bson.Document辅助类.
 *
 * @author admin
 *
 */
public final class DocumentUtil {
	/**
	 * 系统自动添加的id.
	 */
	private static final String ID_IN_MONG_DB = "_id";

	/**
	 * 根据Document创建对象.
	 * @param <T> 创建对象类型.
	 * @param doc 要创建的对象.
	 * @param clazz 对象的类型.
	 * @return 创建的对象.
	 */
	public static <T> T createObject(final Document doc, final Class<T> clazz) {
		if (null == doc) {
			return null;
		}

		String json = doc.toJson();

		if (null == json) {
			return null;
		}

		return JSONObject.parseObject(json, clazz);
	}

	/**
	 * 取得分层属性的第一个属性(多层属性以.分层).
	 * @param field 分层属性，例如afield.bfield.cfiled
	 * @return 属性.
	 */
	public static String getFirstField(final String field) {

		if (null == field) {
			return null;
		}
		if (!field.contains(".")) {
			return field;
		}

		return field.substring(0, field.indexOf("."));
	}

	/**
	 * 根据对象创建Document.
	 *
	 * @param <T> 传入对象类型.
	 * @param t 数据对象.
	 * @return 创建的对象.
	 */
	public static <T> Document createDocument(final T t) {
		String json = JSONObject.toJSONString(t);
		return Document.parse(json);
	}

	/**
	 * 读取Document的int值.
	 *
	 * @param doc 存储数据的对象.
	 * @param key 要读取的属性.
	 * @param defaultValue 失败时,返回的默认值.
	 * @return  获取的数据.
	 */
	public static int getInt(final Document doc, final String key, final int defaultValue) {
		if (null == key || null == doc) {
			return defaultValue;
		}

		if (!key.contains(".")) {
			return doc.getInteger(key, defaultValue);
		}

		String[] arr = key.split("\\.");
		if (arr.length < 2) {
			return doc.getInteger(key, defaultValue);
		}

		Document valDoc = doc;
		for (int i = 0; i < arr.length - 1; i++) {
			if (null == valDoc) {
				break;
			}
			valDoc = (Document) valDoc.get(arr[i]);
		}

		if (null == valDoc) {
			return defaultValue;
		}

		String keyVal = arr[arr.length - 1];
		return valDoc.getInteger(keyVal, defaultValue);
	}

	/**
	 * 读取Document的long值.
	 *
	 * @param doc 存储数据的对象.
	 * @param key 要读取的属性.
	 * @return  获取的数据.
	 */
	public static long getLong(final Document doc, final String key) {
		if (null == key || null == doc) {
			return -1;
		}

		if (!key.contains(".")) {
			return doc.getLong(key);
		}

		String[] arr = key.split("\\.");
		if (arr.length < 2) {
			return doc.getLong(key);
		}

		Document valDoc = doc;
		for (int i = 0; i < arr.length - 1; i++) {
			if (null == valDoc) {
				break;
			}
			valDoc = (Document) valDoc.get(arr[i]);
		}

		if (null == valDoc) {
			return -1;
		}

		String keyVal = arr[arr.length - 1];
		return valDoc.getLong(keyVal);
	}

	/**
	 * 取得Document的bool值.
	 *
	 * @param doc 存储数据的对象.
	 * @param key 要读取的属性.
	 * @param defaultValue 失败时,返回的默认值.
	 * @return  获取的数据.
	 */
	public static boolean getBool(final Document doc, final String key, final boolean defaultValue) {
		if (null == key || null == doc) {
			return defaultValue;
		}

		if (!key.contains(".")) {
			return doc.getBoolean(key, defaultValue);
		}

		String[] arr = key.split("\\.");
		if (arr.length < 2) {
			return doc.getBoolean(key, defaultValue);
		}

		Document valDoc = doc;
		for (int i = 0; i < arr.length - 1; i++) {
			if (null == valDoc) {
				break;
			}
			valDoc = (Document) valDoc.get(arr[i]);
		}

		if (null == valDoc) {
			return defaultValue;
		}

		String keyVal = arr[arr.length - 1];
		return valDoc.getBoolean(keyVal, defaultValue);
	}

	/**
	 * 取得Document的String值.
	 *
	 * @param doc 存储数据的对象.
	 * @param key 要读取的属性.
	 * @return  获取的数据.
	 */
	public static String getString(final Document doc, final String key) {
		if (null == key || null == doc) {
			return "";
		}

		if (!key.contains(".")) {
			return doc.getString(key);
		}

		String[] arr = key.split("\\.");
		if (arr.length < 2) {
			return doc.getString(key);
		}

		Document valDoc = doc;
		for (int i = 0; i < arr.length - 1; i++) {
			if (null == valDoc) {
				break;
			}
			valDoc = (Document) valDoc.get(arr[i]);
		}
		if (null == valDoc) {
			return "";
		}

		String keyVal = arr[arr.length - 1];
		return valDoc.getString(keyVal);
	}

	/**
	 * 取得Document中的子Document.
	 *
	 * @param doc 存储数据的对象.
	 * @param field 要读取的属性.
	 * @return  获取的数据.
	 */
	public static Document getDocumentByField(final Document doc, final String field) {
		if (null == doc) {
			return null;
		}
		if (!doc.containsKey(field)) {
			return null;
		}
		return (Document) doc.get(field);
	}

	/**
	 * 取得Document中的数组.
	 *
	 * @param doc 存储数据的对象.
	 * @param field 要读取的属性.
	 * @return  获取的数据.
	 */
	@SuppressWarnings("unchecked")
	public static List<Document> getArrayByFeild(final Document doc, final String field) {
		if (null == doc) {
			return null;
		}
		if (!field.contains(".")) {
			if (!doc.containsKey(field)) {
				return null;
			}
			return (ArrayList<Document>) doc.get(field);
		}
		String[] arr = field.split("\\.");
		if (arr.length < 2) {
			return (ArrayList<Document>) doc.get(field);
		}

		Document valDoc = doc;
		for (int i = 0; i < arr.length - 1; i++) {
			if (null == valDoc) {
				break;
			}
			valDoc = (Document) valDoc.get(arr[i]);
		}
		if (null == valDoc) {
			return null;
		}

		String keyVal = arr[arr.length - 1];
		return (ArrayList<Document>) valDoc.get(keyVal);
	}

	/**
	 * 将Document集合转换为Json字符串.
	 *
	 * @param docs 存储数据的对象集合.
	 * @return 转换后的字符串.
	 */
	public static String toJson(final List<Document> docs) {
		if (null == docs || docs.size() < 1) {
			return "";
		}

		StringBuilder sb = new StringBuilder();
		sb.append("[");
		for (Document doc : docs) {
			sb.append(DocumentUtil.toJson(doc));
		}
		sb.append("]");
		String json = sb.toString();
		return json.replace("}{", "},{");
	}

	/**
	 * 将Document转换为Json字符串.
	 *
	 * @param doc 存储数据的对象.
	 * @return 转换后的字符串.
	 */
	public static String toJson(final Document doc) {
		if (null == doc) {
			return "";
		}
		if (doc.containsKey(ID_IN_MONG_DB)) {
			doc.remove(ID_IN_MONG_DB);
		}
		return doc.toJson();
	}

	/**
	 * 将Json字符串转换为Document集合.
	 *
	 * @param json Json字符串.
	 * @param docs 将要添加数据的集合.
	 */
	public static void toDocument(final String json, final List<Document> docs) {
		if (null == json || null == docs) {
			return;
		}

		JSONArray jsonArray = JSONArray.parseArray(json);
		if (null == jsonArray) {
			return;
		}

		for (int i = 0; i < jsonArray.size(); i++) {
			JSONObject obj = (JSONObject) jsonArray.get(i);
			if (null == obj) {
				continue;
			}
			String docJson = obj.toString();
			Document doc = Document.parse(docJson);
			if (null == doc) {
				return;
			}
			docs.add(doc);
		}
	}

	/**
	 * 构造函数，放置被误创建，所以生命为private.
	 */
	private DocumentUtil() {
	}
}
